package com.itheima.d3_annotation;

import org.junit.Test;

import java.lang.annotation.*;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/*
    目标：掌握注解的解析。

    AnnotatedElement接口提供了解析注解的方法
        public Annotation[] getDeclaredAnnotations()	获取当前对象上面的注解。
        public T getDeclaredAnnotation(Class<T> annotationClass)	获取指定的注解对象
        public boolean isAnnotationPresent(Class<Annotation> annotationClass)	判断当前对象上是否存在某个注解
 */

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyTest {
    public String value();
    public String name();
}

@MyTest(value = "类上value", name = "类")
class Demo {

    @MyTest(value = "方法的value", name = "方法")
    public void print() {
        System.out.println("===== go go go =====");
    }
}


public class AnnotationTest3 {
    @Test
    public void parseClass() {
        // 1. 获取类对象
        final Class<Demo> clz = Demo.class;

        // 2. 判断类上是否有MyTest注解
        if (clz.isAnnotationPresent(MyTest.class)) {
            final MyTest declaredAnnotation = clz.getDeclaredAnnotation(MyTest.class);
            System.out.println(declaredAnnotation.name());
            System.out.println(declaredAnnotation.value());
        }
    }

    @Test
    public void parseMethod() throws Exception {
        // 1. 获取类对象
        final Class<Demo> clz = Demo.class;
        // 2. 获取类构造器
        final Constructor<Demo> declaredConstructor = clz.getDeclaredConstructor();
        // 3. 创建实例对象
        final Demo demo = declaredConstructor.newInstance();

        // 4. 获取实例方法
        final Method declaredMethod = clz.getDeclaredMethod("print");

        // 5. 调用实例方法
        declaredMethod.invoke(demo);

        // 6. 判断方法是否被注解
        final Method[] declaredMethods = clz.getDeclaredMethods();
        for (Method method : declaredMethods) {
            final MyTest declaredAnnotation = method.getDeclaredAnnotation(MyTest.class);
            // 7. 得到注解绑定的值，方便扩展功能
            System.out.println(declaredAnnotation.name());
            System.out.println(declaredAnnotation.value());

        }


    }
}
